/**
 * Copyright (C), 2020-2021
 * File Name: RpcParamRequest.java
 * Encoding: UTF-8
 * Date: 2021年3月15日 下午2:23:54
 * History:
*/
package com.swak.frame.dto.request;

import java.util.Date;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.collect.Maps;
import com.swak.frame.logger.SwakLoggerFactory;
import com.swak.frame.util.GetterUtil;
import com.swak.frame.util.JacksonUtils;

/**
 * ClassName: RpcParamRequest.java
 * 
 * client 客户端类型 clientVersion 客户端版本 build 客户端小版本号 uuid 客户端设备号 osVersion
 * 客户端操作系统版本 screen 客户端屏幕尺寸 networkType 请求网络类型 partner 合作伙伴 forcebot
 * 全链路测试标识，压测时使用 pin 网关实时验证用户登录态，若通过则会产生pin ip 用户源IP地址 port 用户源端口号 location
 * 根据用户ip计算出的附加信息（不一定能获取到，有降级可能，不要强依赖），格式为"国家_省份_城市_运营商"，示例：中国_湖南_长沙_电信 umg
 * 用户会员级别（不一定能获取到，有降级可能，不要强依赖） urg 用户风险级别（不一定能获取到，有降级可能，不要强依赖） upg
 * plus级别（不一定能获取到，有降级可能，不要强依赖） d_brand 设备品牌 d_model 设备型号 lang 语言 中：zh_CN 英：en_US
 * 泰：th_TH loginType 登录态类型 wqDefault 微信手Q用户标识， true是默认用户， false为非默认 wifiBssid
 * WIFI bssid referer 前端请求携带的HTTP Referer agent 前端请求携带的User-Agent cookie
 * 客户端携带的cookie scope vpn/代理,00:vpn关闭,01:vpn开启,10:网络代理关闭,11:网络代理开启 joycious 京享值
 * eid 设备指纹ID，设备指纹生成的唯一标识 rfs 精细化降级结果 aid Android ID，Android系统提供的设备标识符 oaid
 * 移动安全联盟SDK提供的开放匿名设备标识符 sdkVersion SDK版本号 uts 用户标签加密串 h5sr
 * H5应用验签结果（只有H5类型且开启接口加固的应用调用API时才会生成，不要强依赖）
 * 
 * @author colley.ma
 * @date 2021年3月15日
 */
public class RpcParamRequest extends SwakRequest {
	private static final long serialVersionUID = -7641051200337293578L;

	private final static Logger logger = SwakLoggerFactory.getLogger(RpcParamRequest.class);

	/** 根据用户ip计算出的附加信息，格式为"国家_省份_城市_运营商"，示例：中国_湖南_长沙_电信 */
	private String location;

	/** 客户端类型 */
	private String client;

	/** 客户端携带的cookie */
	private String cookie;

	/** 客户端版本 */
	private String clientVersion;

	/** 客户端小版本号 */
	private String build;

	/** 客户端设备号 */
	private String uuid;

	/** 客户端操作系统版本 */
	private String osVersion;

	/** 客户端屏幕尺寸 */
	private String screen;

	/** 请求网络类型 */
	private String networkType;

	/** 合作伙伴 */
	private String partner;

	/** 全链路测试标识，压测时使用 */
	private String forcebot;

	/** 访问京东时用户IP的原始端口 */
	private String port;

	/** 用户会员级别（不一定能获取到，有降级可能，不要强依赖） */
	private String umg;

	/** 用户风险级别（不一定能获取到，有降级可能，不要强依赖） */
	private String urg;

	/** plus级别（不一定能获取到，有降级可能，不要强依赖） */
	private String upg;

	/** 设备品牌 */
	private String brand;

	/** 设备型号 */
	private String model;

	/** 语言 中：zh_CN 英：en_US 泰：th_TH */
	private String lang;

	/** 微信手Q用户标识， true是默认用户， false为非默认 */
	private String wqDefault;

	/** WIFI bssid */
	private String wifiBssid;

	/** vpn/代理,00:vpn关闭,01:vpn开启,10:网络代理关闭,11:网络代理开启 **/
	private String scope;

	/** 京享值 **/
	private String joycious;

	/** 设备指纹ID，设备指纹生成的唯一标识 **/
	private String eid;

	/** 精细化降级结果 **/
	private String rfs;

	/** Android ID，Android系统提供的设备标识符 **/
	private String aid;

	/** 移动安全联盟SDK提供的开放匿名设备标识符 **/
	private String oaid;

	/** SDK版本号 **/
	private String sdkVersion;

	/** 用户标签加密串 **/
	private String uts;

	/** H5应用验签结果（只有H5类型且开启接口加固的应用调用API时才会生成，不要强依赖） **/
	private String h5sr;

	/** 四级地址e.g 0_1_2_3 **/
	private String area;

	/** 平台类型 **/
	private String platform;

	/*** 业务扩展信息 */
	private Map<String, Object> bizExt = Maps.newHashMap();

	/** 业务参数 Body解析 **/

	private Map<String, String> bizPara = Maps.newHashMap();

	@JsonIgnore
	private transient Map<String, Object> original;

	/**
	 * color 网关
	 *
	 * @param request
	 *
	 * @return
	 */
	public static RpcParamRequest getRpcParamRequest(Map<String, Object> request) {

		logger.info("RpcParamRequest color gateway request:{}", JacksonUtils.toJSONString(request));

		RpcParamRequest.Builder builder = new RpcParamRequest.Builder();
		builder.client(Objects.toString(request.get("client"), null))
				.clientVersion(Objects.toString(request.get("clientVersion"), null))
				.build(Objects.toString(request.get("build"), null)).uuid(Objects.toString(request.get("uuid"), null))
				.osVersion(Objects.toString(request.get("osVersion"), null))
				.screen(Objects.toString(request.get("screen"), null))
				.networkType(Objects.toString(request.get("networkType"), null))
				.partner(Objects.toString(request.get("partner"), null))
				.port(Objects.toString(request.get("port"), null))
				.location(Objects.toString(request.get("location"), null))
				.umg(Objects.toString(request.get("umg"), null)).urg(Objects.toString(request.get("urg"), null))
				.upg(Objects.toString(request.get("upg"), null)).brand(Objects.toString(request.get("d_brand"), null))
				.model(Objects.toString(request.get("d_model"), null)).lang(Objects.toString(request.get("lang"), null))
				.wqDefault(Objects.toString(request.get("wqDefault"), null))
				.wifiBssid(Objects.toString(request.get("wifiBssid"), null))
				.cookie(Objects.toString(request.get("cookie"), null))
				.scope(Objects.toString(request.get("scope"), null))
				.joycious(Objects.toString(request.get("joycious"), null))
				.eid(Objects.toString(request.get("eid"), null)).rfs(Objects.toString(request.get("rfs"), null))
				.aid(Objects.toString(request.get("aid"), null)).oaid(Objects.toString(request.get("oaid"), null))
				.sdkVersion(Objects.toString(request.get("sdkVersion"), null))
				.uts(Objects.toString(request.get("uts"), null)).h5sr(Objects.toString(request.get("h5sr"), null))
				// swakRequest
				.referer(Objects.toString(request.get("referer"), null))
				.agent(Objects.toString(request.get("agent"), null)).appId(Objects.toString(request.get("appid"), null))
				.functionId(Objects.toString(request.get("functionId"), null))
				.forcebot(Objects.toString(request.get("forcebot"), null))// 压测标识
				.pin(Objects.toString(request.get("pin"), null)).ip(Objects.toString(request.get("ip"), null));

		String body = Objects.toString(request.get("body"), null);
		if (StringUtils.isNotEmpty(body)) {
			JsonNode bizPara = JacksonUtils.parseObject(body);
			if (bizPara != null) {
				builder.bizPara(JacksonUtils.toMapString(bizPara));
			}
		}
		// 设置渠道token
		RpcParamRequest rpcParamRequest = builder.build();
		rpcParamRequest.original = request;
		rpcParamRequest.setChannelToken(rpcParamRequest.getStrPara("token"));
		rpcParamRequest.setArea(Objects.toString(request.get("area"), null));
		rpcParamRequest.setUseCase(rpcParamRequest.getStrPara("useCase"));
		return rpcParamRequest;
	}

	public Map<String, Object> getOriginal() {
		return original;
	}

	public String getPlatform() {
		return platform;
	}

	public void setPlatform(String platform) {
		this.platform = platform;
	}

	@Override
	public String getPin() {
		return pin;
	}

	@Override
	public void setPin(String pin) {
		this.pin = pin;
	}

	public String getLocation() {
		return location;
	}

	public void setLocation(String location) {
		this.location = location;
	}

	public String getClient() {
		return client;
	}

	public void setClient(String client) {
		this.client = client;
	}

	@Override
	public String getIp() {
		return ip;
	}

	@Override
	public void setIp(String ip) {
		this.ip = ip;
	}

	public String getCookie() {
		return cookie;
	}

	public void setCookie(String cookie) {
		this.cookie = cookie;
	}

	public String getClientVersion() {
		return clientVersion;
	}

	public void setClientVersion(String clientVersion) {
		this.clientVersion = clientVersion;
	}

	public String getBuild() {
		return build;
	}

	public void setBuild(String build) {
		this.build = build;
	}

	public String getUuid() {
		return uuid;
	}

	public void setUuid(String uuid) {
		this.uuid = uuid;
	}

	public String getOsVersion() {
		return osVersion;
	}

	public void setOsVersion(String osVersion) {
		this.osVersion = osVersion;
	}

	public String getScreen() {
		return screen;
	}

	public void setScreen(String screen) {
		this.screen = screen;
	}

	public String getNetworkType() {
		return networkType;
	}

	public void setNetworkType(String networkType) {
		this.networkType = networkType;
	}

	public String getPartner() {
		return partner;
	}

	public void setPartner(String partner) {
		this.partner = partner;
	}

	@Override
	public String getForcebot() {
		return forcebot;
	}

	@Override
	public void setForcebot(String forcebot) {
		this.forcebot = forcebot;
	}

	public String getPort() {
		return port;
	}

	public void setPort(String port) {
		this.port = port;
	}

	public String getUmg() {
		return umg;
	}

	public void setUmg(String umg) {
		this.umg = umg;
	}

	public String getUrg() {
		return urg;
	}

	public void setUrg(String urg) {
		this.urg = urg;
	}

	public String getUpg() {
		return upg;
	}

	public void setUpg(String upg) {
		this.upg = upg;
	}

	public String getBrand() {
		return brand;
	}

	public void setBrand(String brand) {
		this.brand = brand;
	}

	public String getModel() {
		return model;
	}

	public void setModel(String model) {
		this.model = model;
	}

	public String getLang() {
		return lang;
	}

	public void setLang(String lang) {
		this.lang = lang;
	}

	public String getWqDefault() {
		return wqDefault;
	}

	public void setWqDefault(String wqDefault) {
		this.wqDefault = wqDefault;
	}

	public String getWifiBssid() {
		return wifiBssid;
	}

	public void setWifiBssid(String wifiBssid) {
		this.wifiBssid = wifiBssid;
	}

	@Override
	public String getReferer() {
		return referer;
	}

	@Override
	public void setReferer(String referer) {
		this.referer = referer;
	}

	@Override
	public String getAgent() {
		return agent;
	}

	@Override
	public void setAgent(String agent) {
		this.agent = agent;
	}

	public String getStrPara(String paramName) {
		return getStrPara(paramName, null);
	}

	public String getStrPara(String paramName, String defaultVal) {
		if (this.bizPara == null) {
			return defaultVal;
		}
		return GetterUtil.getString(bizPara.get(paramName), defaultVal);
	}

	public Long getLongPara(String paramName) {
		return getLongPara(paramName, null);
	}

	public Long getLongPara(String paramName, Long defaultVal) {
		String strpara = getStrPara(paramName);
		return GetterUtil.getLong(strpara, defaultVal);
	}

	public Integer getIntegerPara(String paramName) {
		return getIntegerPara(paramName, null);
	}

	public Integer getIntegerPara(String paramName, Integer defaultVal) {
		String strpara = getStrPara(paramName);
		return GetterUtil.getInteger(strpara, defaultVal);
	}

	public Map<String, String> getBizPara() {
		if (bizPara == null) {
			return Maps.newHashMap();
		}
		return bizPara;
	}

	@Override
	public Integer getChannelId() {
		return channelId;
	}

	@Override
	public void setChannelId(Integer channelId) {
		this.channelId = channelId;
	}

	@Override
	public String getAppId() {
		return appId;
	}

	@Override
	public void setAppId(String appId) {
		this.appId = appId;
	}

	public String getScope() {
		return scope;
	}

	public void setScope(String scope) {
		this.scope = scope;
	}

	public String getJoycious() {
		return joycious;
	}

	public void setJoycious(String joycious) {
		this.joycious = joycious;
	}

	public String getEid() {
		return eid;
	}

	public void setEid(String eid) {
		this.eid = eid;
	}

	public String getRfs() {
		return rfs;
	}

	public void setRfs(String rfs) {
		this.rfs = rfs;
	}

	public String getAid() {
		return aid;
	}

	public void setAid(String aid) {
		this.aid = aid;
	}

	public String getOaid() {
		return oaid;
	}

	public void setOaid(String oaid) {
		this.oaid = oaid;
	}

	public String getSdkVersion() {
		return sdkVersion;
	}

	public void setSdkVersion(String sdkVersion) {
		this.sdkVersion = sdkVersion;
	}

	public String getUts() {
		return uts;
	}

	public void setUts(String uts) {
		this.uts = uts;
	}

	public String getArea() {
		return getStrPara("area", area);
	}

	public void setArea(String area) {
		this.area = area;
	}

	public Map<String, Object> getBizExt() {
		return bizExt;
	}

	public void setBizExt(Map<String, Object> bizExt) {
		this.bizExt = bizExt;
	}

	public Object getBizExtPara(String paramName) {
		return bizExt.get(paramName);
	}

	public RpcParamRequest addBizExt(String paramName, Object paramValue) {
		bizExt.put(paramName, paramValue);
		return this;
	}

	@Override
	public Date getFutureTime() {
		return Optional.ofNullable(futureTime).orElse(new Date());
	}

	@Override
	public void setFutureTime(Date futureTime) {
		this.futureTime = futureTime;
	}

	@Override
	public boolean isWhiteList() {
		return whiteList;
	}

	@Override
	public void setWhiteList(boolean whiteList) {
		this.whiteList = whiteList;
	}

	public String getH5sr() {
		return h5sr;
	}

	public void setH5sr(String h5sr) {
		this.h5sr = h5sr;
	}

	@Override
	public Map<String, String> getExtValues() {
		if (extValues.size() == 0) {
			if (this.eid != null) {
				extValues.put("eid", eid);
			}
			if (this.platform != null) {
				extValues.put("platform", platform);
			}
			if (this.osVersion != null) {
				extValues.put("osVersion", osVersion);
			}
			if (this.uuid != null) {
				extValues.put("uuid", uuid);
			}
			if (this.networkType != null) {
				extValues.put("networkInfo", networkType);
			}
			if (this.client != null) {
				extValues.put("client", client);
			}
			if (this.clientVersion != null) {
				extValues.put("clientVersion", clientVersion);
			}
			if (this.model != null) {
				extValues.put("mobileModel", model);
			}
			if (this.brand != null) {
				extValues.put("mobileBrand", brand);
			}
			if (this.screen != null) {
				extValues.put("screen", screen);
			}
		}
		return extValues;
	}

	public static class Builder extends SwakRequest.Builder {
		private String location;
		private String client;
		private String cookie;
		private String clientVersion;
		private String build;
		private String uuid;
		private String osVersion;
		private String screen;
		private String networkType;
		private String partner;
		private String port;
		private String umg;
		private String urg;
		private String upg;
		private String brand;
		private String model;
		private String lang;
		private String wqDefault;
		private String wifiBssid;
		private String scope;
		private String joycious;
		private String eid;
		private String rfs;
		private String aid;
		private String oaid;
		private String sdkVersion;
		private String uts;
		private String h5sr;
		private String platform;
		private Map<String, String> bizPara;

		public Builder location(String location) {
			this.location = location;
			return this;
		}

		public Builder client(String client) {
			this.client = client;
			return this;
		}

		public Builder cookie(String cookie) {
			this.cookie = cookie;
			return this;
		}

		public Builder clientVersion(String clientVersion) {
			this.clientVersion = clientVersion;
			return this;
		}

		public Builder build(String build) {
			this.build = build;
			return this;
		}

		public Builder uuid(String uuid) {
			this.uuid = uuid;
			return this;
		}

		public Builder osVersion(String osVersion) {
			this.osVersion = osVersion;
			return this;
		}

		public Builder screen(String screen) {
			this.screen = screen;
			return this;
		}

		public Builder networkType(String networkType) {
			this.networkType = networkType;
			return this;
		}

		public Builder partner(String partner) {
			this.partner = partner;
			return this;
		}

		public Builder port(String port) {
			this.port = port;
			return this;
		}

		public Builder umg(String umg) {
			this.umg = umg;
			return this;
		}

		public Builder urg(String urg) {
			this.urg = urg;
			return this;
		}

		public Builder upg(String upg) {
			this.upg = upg;
			return this;
		}

		public Builder brand(String brand) {
			this.brand = brand;
			return this;
		}

		public Builder model(String model) {
			this.model = model;
			return this;
		}

		public Builder lang(String lang) {
			this.lang = lang;
			return this;
		}

		public Builder wqDefault(String wqDefault) {
			this.wqDefault = wqDefault;
			return this;
		}

		public Builder wifiBssid(String wifiBssid) {
			this.wifiBssid = wifiBssid;
			return this;
		}

		public Builder scope(String scope) {
			this.scope = scope;
			return this;
		}

		public Builder joycious(String joycious) {
			this.joycious = joycious;
			return this;
		}

		public Builder eid(String eid) {
			this.eid = eid;
			return this;
		}

		public Builder rfs(String rfs) {
			this.rfs = rfs;
			return this;
		}

		public Builder aid(String aid) {
			this.aid = aid;
			return this;
		}

		public Builder oaid(String oaid) {
			this.oaid = oaid;
			return this;
		}

		public Builder sdkVersion(String sdkVersion) {
			this.sdkVersion = sdkVersion;
			return this;
		}

		public Builder uts(String uts) {
			this.uts = uts;
			return this;
		}

		public Builder h5sr(String h5sr) {
			this.h5sr = h5sr;
			return this;
		}

		public Builder platform(String platform) {
			this.platform = platform;
			return this;
		}

		public Builder bizPara(Map<String, String> bizPara) {
			this.bizPara = bizPara;
			return this;
		}

		@Override
		public RpcParamRequest build() {
			return new RpcParamRequest(this);
		}
	}

	private RpcParamRequest(Builder builder) {
		super(builder);
		this.location = builder.location;
		this.client = builder.client;
		this.cookie = builder.cookie;
		this.clientVersion = builder.clientVersion;
		this.build = builder.build;
		this.uuid = builder.uuid;
		this.osVersion = builder.osVersion;
		this.screen = builder.screen;
		this.networkType = builder.networkType;
		this.partner = builder.partner;
		this.port = builder.port;
		this.umg = builder.umg;
		this.urg = builder.urg;
		this.upg = builder.upg;
		this.brand = builder.brand;
		this.model = builder.model;
		this.lang = builder.lang;
		this.wqDefault = builder.wqDefault;
		this.wifiBssid = builder.wifiBssid;
		this.scope = builder.scope;
		this.joycious = builder.joycious;
		this.eid = builder.eid;
		this.rfs = builder.rfs;
		this.aid = builder.aid;
		this.oaid = builder.oaid;
		this.sdkVersion = builder.sdkVersion;
		this.uts = builder.uts;
		this.h5sr = builder.h5sr;
		this.platform = builder.platform;
		this.bizPara = builder.bizPara;
	}

	public static void main(String[] args) {
		Map<String, Object> request = Maps.newConcurrentMap();
		request.put("pin", "colley_ma");
		Map<String, Object> body = Maps.newConcurrentMap();
		body.put("token", "");

		request.put("body", JacksonUtils.toJSONString(body));

		System.err.println(JacksonUtils.toJSONString(request));

		System.err.println(JacksonUtils.toJSONString(getRpcParamRequest(request)));
	}
}
